//
//  WCImageManager.m
//  WC
//
//  Created by 杨鑫 on 15/5/21.
//  Copyright (c) 2015年 智康. All rights reserved.
//

#import "WCImageManager.h"
#import "WCNetworkAccessManager.h"
#import "WCPopupLayerManager.h"
//
#import "Macros.h"
#import "WCDefaultManager.h"
#import "SDWebImageManager.h"

static NSString *nursePath = @"Images/nurse";
static NSString *patientPath = @"Images/patient";
static NSString *privatePath = @"Images/private";
static NSString *publicPath = @"Images/public";
static NSString *uploadPath = @"ImagesWaitForUpload";

@interface WCImageManager ()

@property (strong, nonatomic) NSCache *imageCache;

@property (strong, nonatomic) AFHTTPSessionManager *downloadManager;
@property (strong, nonatomic) AFHTTPSessionManager *uploadManager;

@property (strong, nonatomic) NSMutableDictionary *downsDic;
@property (strong, nonatomic) NSMutableDictionary *downBlockArray;

@property (strong, nonatomic) NSString *bathURL;
@property (strong, nonatomic) NSString *mediaURL;

@property (strong, nonatomic) NSString *nurseAvatarDir;
@property (strong, nonatomic) NSString *patientAvatarDir;
@property (strong, nonatomic) NSString *privateDir;
@property (strong, nonatomic) NSString *publicDir;
@property (strong, nonatomic) NSString *uploadDir;

@property (strong, nonatomic) dispatch_queue_t queue;

@end

@implementation WCImageManager

+ (instancetype)sharedMg
{
    static WCImageManager *sharedMg = nil;
    //block
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMg = [[WCImageManager alloc] initPrivate];
    });
    
    return sharedMg;
}

- (instancetype)init
{
    @throw [NSException exceptionWithName:@"Singleton"
                                   reason:@"Use + [WCImageManager sharedMg]"
                                 userInfo:nil];
    return nil;
}

- (instancetype)initPrivate
{
    self = [super init];
    if (self) {
        _imageCache = [[NSCache alloc] init];
        
        _downloadManager = [AFHTTPSessionManager manager];
        _downloadManager.responseSerializer = [AFImageResponseSerializer serializer];
        _uploadManager = [AFHTTPSessionManager manager];
        
        _downsDic = [NSMutableDictionary dictionary];
        _downBlockArray = [NSMutableDictionary dictionary];
        
        //        _queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        _queue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
        
        dispatch_async(_queue, ^{
            NSDictionary *configs = [NSDictionary dictionaryWithContentsOfFile:[self getConfigFilePath]];
            NSString *model = nil;
#if DEBUG
            model = configs[@"MODEL"];
           
            
#else
            model =@"ali";
            
#endif
            self.bathURL = configs[@"URLS"][model];
            self.mediaURL = configs[@"MEDIAS"][model];
            
            self.nurseAvatarDir = [self createPicDir:nursePath];
            self.patientAvatarDir = [self createPicDir:patientPath];
            self.privateDir = [self createPicDir:privatePath];
            self.publicDir = [self createPicDir:publicPath];
            self.uploadDir = [self createPicDir:uploadPath];
        });
        
//        [[WCNetworkAccessManager sharedMg] GET:@"system/config/json/media/url" parameters:nil success:^(NSDictionary *url){
//            self.mediaURL = url[@"data"];
//        } failure:nil netError:nil always:nil];
        NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[self getConfigFilePath]];
        NSDictionary *subDict =dict[@"MEDIAS"];
        NSString *item =dict[@"MODEL"];
        self.mediaURL =subDict[item];
        [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:nil usingBlock:^(NSNotification *note){
            [self.imageCache removeAllObjects];
        }];
    }
    return self;
}

- (NSString *)getConfigFilePath
{
    return [[NSBundle mainBundle] pathForResource:@"config" ofType:@"plist"];
}
#pragma mark - Cache

- (void)deleteImgs
{
    dispatch_async(self.queue, ^{
        NSFileManager *fm = [NSFileManager defaultManager];
        NSString *imagesPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Images"];
        [fm removeItemAtPath:imagesPath error:nil];
        
        self.nurseAvatarDir = [self createPicDir:nursePath];
        self.patientAvatarDir = [self createPicDir:patientPath];
        self.privateDir = [self createPicDir:privatePath];
        self.publicDir = [self createPicDir:publicPath];
    });
}

- (void)deletePrivateImgs
{
    dispatch_async(self.queue, ^{
        NSFileManager *fm = [NSFileManager defaultManager];
        [fm removeItemAtPath:self.nurseAvatarDir error:nil];
        [fm removeItemAtPath:self.patientAvatarDir error:nil];
        [fm removeItemAtPath:self.privateDir error:nil];
        
        self.nurseAvatarDir = [self createPicDir:nursePath];
        self.patientAvatarDir = [self createPicDir:patientPath];
        self.privateDir = [self createPicDir:privatePath];
    });
}

- (void)deleteImgsByType:(WCImageType)type
{
    dispatch_async(self.queue, ^{
        NSFileManager *fm = [NSFileManager defaultManager];
        switch (type) {
            case WCImageTypeNurse: {
                [fm removeItemAtPath:self.nurseAvatarDir error:nil];
                self.nurseAvatarDir = [self createPicDir:nursePath];
                break;
            }
            case WCImageTypePatient: {
                [fm removeItemAtPath:self.patientAvatarDir error:nil];
                self.patientAvatarDir = [self createPicDir:patientPath];
                break;
            }
            case WCImageTypePrivateImage: {
                [fm removeItemAtPath:self.privateDir error:nil];
                self.privateDir = [self createPicDir:privatePath];
                break;
            }
            case WCImageTypeImage: {
                [fm removeItemAtPath:self.publicDir error:nil];
                self.publicDir = [self createPicDir:publicPath];
                break;
            }
        }
    });
}

- (void)removeImgsCache
{
    [self.imageCache removeAllObjects];
}

- (void)deleteImageAfterUpload:(NSString *)name
{
    dispatch_async(self.queue, ^{
        NSString *path = [self.uploadDir stringByAppendingPathComponent:name];
        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
    });
}

- (void)saveImageWaitUpload:(UIImage *)image byName:(NSString *)name;
{
//    dispatch_async(self.queue, ^{
        NSString *path = [self.uploadDir stringByAppendingPathComponent:name];
        NSData *data = UIImagePNGRepresentation(image);
        [data writeToFile:path atomically:YES];
//    });
}

- (void)imgsSize:(void(^)(float))success;
{
    dispatch_async(self.queue, ^{
        float size = .0f;
        size += [self folderSizeAtPath:self.nurseAvatarDir];
        size += [self folderSizeAtPath:self.patientAvatarDir];
        size += [self folderSizeAtPath:self.privateDir];
        size += [self folderSizeAtPath:self.publicDir];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            success(size);
        });
    });
}

#pragma mark - pic

- (NSURLSessionDataTask *)downloadImage:(NSString *)stringId
                                     type:(WCImageType)type
                                     size:(WCImageSize)size
                                    cache:(BOOL)cache
                                  success:(void (^)(UIImage *image, NSString *stringId))success
                                  failure:(void (^)(NSError *error))failure
{
    
    
    NSString *imageURLString = [self getURL:stringId type:type size:size];
    NSString *path = [self getPath:stringId type:type size:size];
    
    void(^downSuccess)(NSURLSessionDataTask *, UIImage *) = ^(NSURLSessionDataTask *operation, UIImage *image){
        //删除保存的下载操作
        [self.downsDic removeObjectForKey:imageURLString];
        
        [self saveImage:image toPath:path success:^(UIImage *localImage){
            if (localImage ==nil) {
                return ;
            }
            //缓存图片
            if (cache) {
                [self.imageCache setObject:localImage forKey:imageURLString];
            }
            //执行回调队列
            NSMutableArray *array = [self.downBlockArray objectForKey:imageURLString];
            for (int i=0; i<array.count; i++) {
                void(^successBlock)(UIImage *image, NSString *stringId) = array[i];
                successBlock(localImage, stringId);
            }
            //删除回调队列
            [self.downBlockArray removeObjectForKey:imageURLString];
        }];
    };
    
    void(^downFailure)(NSURLSessionDataTask *, NSError *) = ^(NSURLSessionDataTask *task, NSError *error){
        
        NSLog(@"下载图片失败%@",error.localizedDescription);
        [self.downsDic removeObjectForKey:imageURLString];
        [self.downBlockArray removeObjectForKey:imageURLString];
        
        failure?failure(error):nil;
    };
    
    NSURLSessionDataTask *task = [self.downsDic objectForKey:imageURLString];
    if (task) {
        //图片正在下载，block加入到等候队列
        NSMutableArray *array = [self.downBlockArray objectForKey:imageURLString];
        [array addObject:[success copy]];
    } else {
        if (size == WCImageSizeSmall) {
            [self deleteImg:stringId type:type size:WCImageSizeBig];
        }
        
        task = [self.downloadManager GET:imageURLString parameters:nil progress:nil success:downSuccess failure:downFailure];
        //下载操作保存在字典中
        [self.downsDic setObject:task forKey:imageURLString];
        //创建等候队列
        NSMutableArray *array = [NSMutableArray arrayWithObjects:[success copy], nil];
        [self.downBlockArray setObject:array forKey:imageURLString];
    }
    
    //下载进度由每个视图控制器自己去完成
//    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead){}];
    
    return task;
}

- (NSURLSessionDataTask *)uploadImage:(NSArray *)images
                                  multi:(BOOL)multi
                                progress:(void(^)(NSProgress *progress))up_progerss
                                success:(void (^)(id responseObject))success
                                failure:(void (^)(NSString *msg))failure
{
    NSString *uploadUrl = [NSString stringWithFormat:@"%@/%@", self.mediaURL, multi?@"images":@"image"];
   
   
    NSURLSessionDataTask *task = [self.uploadManager POST:uploadUrl parameters:@{@"app": @"NURSE"} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        for (int i=0; i<images.count; i++) {
            UIImage *image = images[i];
            NSData *imageData = UIImagePNGRepresentation(image);
            if (!imageData) {
                imageData = UIImageJPEGRepresentation(image, 0.6);
            }
            [formData appendPartWithFileData:imageData name:multi?@"files":@"file" fileName:[NSString stringWithFormat:@"file%d.png", i] mimeType:@"image/png"];
        }
    } progress:up_progerss success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *result = responseObject;
        BOOL isSuccess = [result[@"success"] boolValue];
        if (isSuccess) {
            success(result);
        } else {
            failure?failure(result[@"errMsg"]):nil;
        }
 
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        Log(@"---%@",error);
        //查看网络错误的原因
        failure?failure(@"网络异常"):nil;
    }];
    
    return task;
}

- (UIImage *)image:(NSString *)stringId type:(WCImageType)type size:(WCImageSize)size cache:(BOOL)cache
{
    if (cache) {
        NSString *imageURLString = [self getURL:stringId type:type size:size];
        UIImage *image = [self.imageCache objectForKey:imageURLString];
        if (!image) {
            NSString *path = [self getPath:stringId type:type size:size];
            image = [UIImage imageWithContentsOfFile:path];
            if (image) {
                [self.imageCache setObject:image forKey:imageURLString];
            }
        }
        
        return image;
    } else {
        NSString *path = [self getPath:stringId type:type size:size];
        return [UIImage imageWithContentsOfFile:path];
    }
}

- (UIImage *)imageForUpload:(NSString *)name
{
    NSString *path = [self.uploadDir stringByAppendingPathComponent:name];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:path]) {
        return [UIImage imageWithContentsOfFile:path];
    }
    return nil;
}

- (BOOL)hasImage:(NSString *)stringId type:(WCImageType)type size:(WCImageSize)size
{
    NSString *path = [self getPath:stringId type:type size:size];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:path]) {
        return YES;
    }
    return NO;
}

#pragma mark - Private

- (NSString *)getURL:(NSString *)name type:(WCImageType)type size:(WCImageSize)size
{
  
    NSString *url;
    
    if (size == WCImageSizeSmall) {
        url = @"simg";
    } else if (size == WCImageSizeBig) {
        url = @"img";
    }
    
    switch (type) {
        case WCImageTypeNurse: {
            url = [NSString stringWithFormat:@"%@/avatar/%@/nurse/%@", self.bathURL, url, name];
            break;
        }
        case WCImageTypePatient: {
            url = [NSString stringWithFormat:@"%@/avatar/%@/patient/%@", self.bathURL, url, name];
            break;
        }
        default:{
            url = [NSString stringWithFormat:@"%@/image/%@/%@", self.mediaURL, url, name];
            break;
        }
    }
//    NSLog(@"图片地址%@",url);
    return url;
}

#pragma mark - path

- (NSString *)getPath:(NSString *)name type:(WCImageType)type size:(WCImageSize)size
{
    NSString *path;
    
    if (size == WCImageSizeSmall) {
        path = [NSString stringWithFormat:@"simg%@", name];
    } else if (size == WCImageSizeBig) {
        path = [NSString stringWithFormat:@"img%@", name];
    }
    
    switch (type) {
        case WCImageTypeNurse: {
            path = [self.nurseAvatarDir stringByAppendingPathComponent:path];
            break;
        }
        case WCImageTypePatient: {
            path = [self.patientAvatarDir stringByAppendingPathComponent:path];
            break;
        }
        case WCImageTypePrivateImage: {
            path = [self.privateDir stringByAppendingPathComponent:path];
            break;
        }
        case WCImageTypeImage: {
            path = [self.publicDir stringByAppendingPathComponent:path];
            break;
        }
    }
    
    return path;
}

- (NSString *)createPicDir:(NSString *)path
{
    NSFileManager *fm = [NSFileManager defaultManager];
    NSString *docPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    
    NSString *rootPath = [docPath stringByAppendingPathComponent:path];
    if (![fm fileExistsAtPath:rootPath isDirectory:nil]) {
        [fm createDirectoryAtPath:rootPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return rootPath;
}



#pragma mark - file

- (void)saveImage:(UIImage *)image toPath:(NSString *)path success:(void(^)(UIImage *))success
{
#warning 在这里发现一个问题，因为在护理师列表每次下拉刷新成功，就会删除护理师头像，下拉太快太平凡是，可能在读取下载好的图片前，新下载的图片就被删除拉，所以localImage出现nil,导致程序闪退.(因为删除图片和保存图片都是异步执行的, 所以才发生这样的问题)。有时候tableViewCell的图片出不来也是这个原因
    
#warning 互斥的异步
    dispatch_barrier_async(self.queue, ^{
        NSData *data = UIImagePNGRepresentation(image);
        UIImage *localImage;
        if ([data writeToFile:path atomically:YES]) {
            localImage = [UIImage imageWithContentsOfFile:path];
        } else {
            localImage = image;
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            success?success(localImage):^{};
        });
    });
}

- (void)deleteImg:(NSString *)stringId type:(WCImageType)type size:(WCImageSize)size
{
    NSString *imageURLString = [self getURL:stringId type:type size:size];
    [self.imageCache removeObjectForKey:imageURLString];
    
    dispatch_async(self.queue, ^{
        NSString *path = [self getPath:stringId type:type size:size];
        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
    });
}

//单个文件的大小
- (long long)fileSizeAtPath:(NSString*)filePath
{
    NSFileManager* manager = [NSFileManager defaultManager];
    if ([manager fileExistsAtPath:filePath]){
        return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
    }
    return 0;
}

//遍历文件夹获得文件夹大小，返回多少M
- (float)folderSizeAtPath:(NSString*)folderPath
{
    NSFileManager* manager = [NSFileManager defaultManager];
    if (![manager fileExistsAtPath:folderPath])
        return 0;
    
    NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath:folderPath] objectEnumerator];
    NSString* fileName;
    long long folderSize = 0;
    while ((fileName = [childFilesEnumerator nextObject]) != nil){
        NSString* fileAbsolutePath = [folderPath stringByAppendingPathComponent:fileName];
        folderSize += [self fileSizeAtPath:fileAbsolutePath];
    }
    return folderSize/(1024.0*1024.0);
}
- (NSURLSessionDataTask *)uploadMultiImage:(NSArray *)imageArray
                                     success:(void (^)(id responseObject))success
                                     failure:(void (^)(NSString *msg))failure
                                      always:(void (^)(void)) always
{
    NSString *uploadUrl = [NSString stringWithFormat:@"%@/images", self.mediaURL];
    
    NSURLSessionDataTask *task = [self.uploadManager POST:uploadUrl parameters:@{@"app": @"PATIENT"} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        for (UIImage *image in imageArray) {
            int i =0;
            NSData *imageData =  UIImageJPEGRepresentation(image, 0.6);
            
            
            [formData appendPartWithFileData:imageData name:@"files" fileName:[NSString stringWithFormat:@"orderInforPic%i.png",i++] mimeType:@"image/png"];
            
        }
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *result = responseObject;
        BOOL isSuccess = [result[@"success"] boolValue];
        if (isSuccess) {
            success(result);
        } else {
            if (failure) {
                failure(result[@"errMsg"]);
            } else {
                [[WCPopupLayerManager shareMg] showTextOnly:result[@"errMsg"] withView:[UIApplication sharedApplication].keyWindow];
            }
        }
        if (always) {
            always();
        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (always) {
            always();
        }
    }];
    
    
    
//    [self.uploadManager POST:uploadUrl parameters:@{@"app": @"PATIENT"} constructingBodyWithBlock:^(id <AFMultipartFormData> formData){
//        
//        
//        for (UIImage *image in imageArray) {
//            int i =0;
//            NSData *imageData =  UIImageJPEGRepresentation(image, 0.6);
//            
//            
//            [formData appendPartWithFileData:imageData name:@"files" fileName:[NSString stringWithFormat:@"orderInforPic%i.png",i++] mimeType:@"image/png"];
//            
//        }
//        
//    } success:^(AFHTTPRequestOperation *operation, id responseObject){
//       
//        //        Log(@"data %@", responseObject);
//        
//        NSDictionary *result = responseObject;
//        BOOL isSuccess = [result[@"success"] boolValue];
//        if (isSuccess) {
//            success(result);
//        } else {
//            if (failure) {
//                failure(result[@"errMsg"]);
//            } else {
//                [[WCPopupLayerManager shareMg] showTextOnly:result[@"errMsg"] withView:[UIApplication sharedApplication].keyWindow];
//            }
//        }
//        if (always) {
//            always();
//        }
//        
//    } failure:^(AFHTTPRequestOperation *operation, NSError *error){
//        if (always) {
//            always();
//        }
//    }];
    
    //上传进度由每个视图控制器自己去完成
    //    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite){}];
    
    return task;
}
+ (void)downLoadOriImage:(NSString *)url completed:(void(^)(UIImage *image))comleteBolck
{
    NSString *path =[[NSBundle mainBundle] pathForResource:@"config" ofType:@"plist"];
    NSDictionary *plistDict =[NSDictionary dictionaryWithContentsOfFile:path];
    NSString *priod = plistDict[@"MODEL"];
    NSString *bathUrl =[plistDict[@"MEDIAS"] objectForKey:priod];
    NSString *newStr =[NSString stringWithFormat:@"%@%@%@",bathUrl,@"/image/img/",url];
    [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:newStr] options:SDWebImageCacheMemoryOnly progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
        if (comleteBolck) {
            if (image) {
                comleteBolck(image);
            }else{
                //                 comleteBolck([UIImage imageNamed:@"nurse"]);
            }
            
        }
    }];
    
}

@end
